//http://www.jiazhengblog.com/blog/2017/01/04/2989/

namespace FIREFLYX {
    /** 混合因子 */
    export enum BlendFactor {
        /** 值为 0 */
        ZERO = WebGL2RenderingContext.ZERO,
        /** 值为 1 */
        ONE = WebGL2RenderingContext.ONE,
        /** 值为 当前像素RGBA */
        SRC_COLOR = WebGL2RenderingContext.SRC_COLOR,
        /** 值为 (1 - 当前像素RGBA) */
        ONE_MINUS_SRC_COLOR = WebGL2RenderingContext.ONE_MINUS_SRC_COLOR,
        /** 值为 已有像素RGBA */
        DST_COLOR = WebGL2RenderingContext.DST_COLOR,
        /** 值为 (1 - 已有像素RGBA) */
        ONE_MINUS_DST_COLOR = WebGL2RenderingContext.ONE_MINUS_DST_COLOR,
        /** 值为 当前像素Alpha */
        SRC_ALPHA = WebGL2RenderingContext.SRC_ALPHA,
        /** 值为 (1 - 当前像素Alpha) */
        ONE_MINUS_SRC_ALPHA = WebGL2RenderingContext.ONE_MINUS_SRC_ALPHA,
        /** 值为 已有像素Alpha */
        DST_ALPHA = WebGL2RenderingContext.DST_ALPHA,
        /** 值为 (1 - 已有像素Alpha) */
        ONE_MINUS_DST_ALPHA = WebGL2RenderingContext.ONE_MINUS_DST_ALPHA,
        /** 值为 min(当前像素Alpha , 1 - 已有像素Alpha) */
        SRC_ALPHA_SATURATE = WebGL2RenderingContext.SRC_ALPHA_SATURATE
    }

    /** 混合的方程式 */
    export enum BlendEquation {
        /** 相加 */
        FUNC_ADD = WebGL2RenderingContext.FUNC_ADD,
        /** 当前像素(src) 减去 已有像素(dest) */
        FUNC_SUBTRACT = WebGL2RenderingContext.FUNC_SUBTRACT,
        /** 已有像素(dest) 减去 当前像素(src) */
        FUNC_REVERSE_SUBTRACT = WebGL2RenderingContext.FUNC_REVERSE_SUBTRACT,
        /** 已有像素(dest) 与 当前像素(src) 中取最小值 */
        FUNC_MIN = WebGL2RenderingContext.MIN,
        /** 已有像素(dest) 与 当前像素(src) 中取最大值 */
        FUNC_MAX = WebGL2RenderingContext.MAX,
    }

    export class BlendState {
        private static cacheStateMap: { [key: string]: BlendState } = {};
        private states: number[];
        // eslint-disable-next-line no-useless-constructor
        private constructor() {
            //
        }

        /** 当前像素因子 */
        public get src(): BlendFactor { return this.states[0]; }
        /** 已有像素因子 */
        public get dst(): BlendFactor { return this.states[1]; }
        /** 像素混合的方程式 */
        public get equation(): BlendEquation { return this.states[2]; }
        /** 当前像素Alpha因子 (值为null 无效)*/
        public get srcAlpha(): Nullable<BlendFactor> { return this.states[3] == 0 ? null : this.states[3]; }
        /** 已有像素Alpha因子 (值为null 无效)*/
        public get dstAlpha(): Nullable<BlendFactor> { return this.states[4] == 0 ? null : this.states[4]; }
        /** 像素Alpha混合的方程式 (值为null 无效)*/
        public get equationAlpha(): Nullable<BlendEquation> { return this.states[5] == 0 ? null : this.states[5]; }

        /**
         * 获取像素混合状态
         * @param src 当前像素因子
         * @param dst 已有像素因子
         * @param equation 像素混合的方程式
         * @param srcAlpha 当前像素Alpha因子
         * @param dstAlpha 已有像素Alpha因子
         * @param equationAlpha 像素Alpha混合的方程式
         * @returns 混合状态
         */
        public static getState(src = BlendFactor.SRC_ALPHA, dst = BlendFactor.ONE_MINUS_SRC_ALPHA, equation: BlendEquation = BlendEquation.FUNC_ADD,
            srcAlpha: Nullable<BlendFactor> = null, dstAlpha: Nullable<BlendFactor> = null, equationAlpha = BlendEquation.FUNC_ADD) {

            let stateKey = `${src}_${dst}_${equation}`;
            let alphaMode = srcAlpha != null && dstAlpha != null;
            if (alphaMode) {
                stateKey += `_${srcAlpha}_${dstAlpha}_${equationAlpha}`;
            }
            let state = this.cacheStateMap[stateKey];
            if (!state) {
                this.cacheStateMap[stateKey] = state = new BlendState();
                if (!alphaMode) {
                    state.states = [src, dst, equation, 0, 0, 0];
                } else {
                    state.states = [src, dst, equation, Number(srcAlpha), Number(dstAlpha), equationAlpha];
                }
            }
            return state;
        }
    }
}